--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Commit 4186ea95e6e252437851973807a7f1a0fe0ab642
Parents : 60a4c6a
Author : Ivan <ivan@quad4.io>
Signature : Invalid signer <e46112d44649266d71fe2193e00a4710>, author is <ivan@quad4.io>
Date : 2026-07-02T22:20:05-05:00
chore(build): refactor macOS CI scripts to streamline Python dependency installation and unify backend file handling
Changes
6 files changed, 81 insertions(+), 48 deletions(-)
Diff
diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml
index 409ac358..340226a6 100644
--- a/.github/workflows/build-release.yml
+++ b/.github/workflows/build-release.yml
@@ -445,10 +445,6 @@ jobs:
architecture: x64
update-environment: false
- - name: Export PYTHON_CMD_X64 for mac universal build
- if: matrix.label == 'macos'
- run: echo "PYTHON_CMD_X64=${{ steps.python_x64.outputs.python-path }}" >> "$GITHUB_ENV"
-
- name: Install x86_64 libyaml for universal cx_Freeze slice
if: matrix.label == 'macos'
run: |
@@ -480,26 +476,7 @@ jobs:
if: matrix.label == 'macos'
env:
PY_X64: ${{ steps.python_x64.outputs.python-path }}
- ARCHFLAGS: "-arch x86_64"
- CC: "clang -arch x86_64"
- CXX: "clang++ -arch x86_64"
- CFLAGS: "-arch x86_64"
- run: |
- set -euo pipefail
- _codec2="$(arch -x86_64 /usr/local/bin/brew --prefix codec2)"
- arch -x86_64 /usr/local/bin/brew install openssl@3
- _openssl="$(arch -x86_64 /usr/local/bin/brew --prefix openssl@3)"
- export LDFLAGS="-L${_codec2}/lib -L${_openssl}/lib -arch x86_64"
- export CPPFLAGS="-I${_codec2}/include -I${_openssl}/include -arch x86_64"
- export PKG_CONFIG_PATH="${_codec2}/lib/pkgconfig:${_openssl}/lib/pkgconfig:/usr/local/lib/pkgconfig:/usr/local/share/pkgconfig"
- export OPENSSL_DIR="${_openssl}"
- export OPENSSL_LIB_DIR="${_openssl}/lib"
- export OPENSSL_INCLUDE_DIR="${_openssl}/include"
- arch -x86_64 "$PY_X64" -m pip install -U pip setuptools wheel
- arch -x86_64 "$PY_X64" -m pip install --prefer-binary "cryptography==49.0.0"
- arch -x86_64 "$PY_X64" -m pip install "cx-freeze>=7.0.0"
- arch -x86_64 "$PY_X64" -m pip install -e .
- arch -x86_64 "$PY_X64" scripts/patch_lxst_pyogg_ogg_ctypes.py
+ run: bash scripts/ci/github-install-macos-x64-python-deps.sh
- name: Download frontend artifact
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 6faa134b..854597ae 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -111,10 +111,6 @@ jobs:
architecture: x64
update-environment: false
- - name: Export PYTHON_CMD_X64 for mac universal build
- if: matrix.label == 'macos'
- run: echo "PYTHON_CMD_X64=${{ steps.python_x64.outputs.python-path }}" >> "$GITHUB_ENV"
-
- name: Install x86_64 codec2 for pycodec2 (universal slice)
if: matrix.label == 'macos'
run: |
@@ -129,26 +125,7 @@ jobs:
if: matrix.label == 'macos'
env:
PY_X64: ${{ steps.python_x64.outputs.python-path }}
- ARCHFLAGS: "-arch x86_64"
- CC: "clang -arch x86_64"
- CXX: "clang++ -arch x86_64"
- CFLAGS: "-arch x86_64"
- run: |
- set -euo pipefail
- _codec2="$(arch -x86_64 /usr/local/bin/brew --prefix codec2)"
- arch -x86_64 /usr/local/bin/brew install openssl@3
- _openssl="$(arch -x86_64 /usr/local/bin/brew --prefix openssl@3)"
- export LDFLAGS="-L${_codec2}/lib -L${_openssl}/lib -arch x86_64"
- export CPPFLAGS="-I${_codec2}/include -I${_openssl}/include -arch x86_64"
- export PKG_CONFIG_PATH="${_codec2}/lib/pkgconfig:${_openssl}/lib/pkgconfig:/usr/local/lib/pkgconfig:/usr/local/share/pkgconfig"
- export OPENSSL_DIR="${_openssl}"
- export OPENSSL_LIB_DIR="${_openssl}/lib"
- export OPENSSL_INCLUDE_DIR="${_openssl}/include"
- arch -x86_64 "$PY_X64" -m pip install -U pip setuptools wheel
- arch -x86_64 "$PY_X64" -m pip install --prefer-binary "cryptography==49.0.0"
- arch -x86_64 "$PY_X64" -m pip install "cx-freeze>=7.0.0"
- arch -x86_64 "$PY_X64" -m pip install -e .
- arch -x86_64 "$PY_X64" scripts/patch_lxst_pyogg_ogg_ctypes.py
+ run: bash scripts/ci/github-install-macos-x64-python-deps.sh
- name: Download frontend artifact
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0
diff --git a/scripts/build-macos-universal.sh b/scripts/build-macos-universal.sh
index 7a141c89..7a45744f 100644
--- a/scripts/build-macos-universal.sh
+++ b/scripts/build-macos-universal.sh
@@ -50,6 +50,8 @@ if [[ -f "$_arm_miniaudio" ]]; then
fi
if [[ -n "${PYTHON_CMD_X64:-}" ]]; then
cross-env ARCH=x64 PYTHON_CMD="$PYTHON_CMD_X64" pnpm run build-backend
+elif [[ -x "$ROOT/.venv-x64/bin/python" ]]; then
+ cross-env ARCH=x64 PYTHON_CMD="$ROOT/.venv-x64/bin/python" pnpm run build-backend
else
cross-env ARCH=x64 pnpm run build-backend
fi
diff --git a/scripts/ci/github-install-deps.sh b/scripts/ci/github-install-deps.sh
index 1cfba3b2..5ae59d97 100755
--- a/scripts/ci/github-install-deps.sh
+++ b/scripts/ci/github-install-deps.sh
@@ -32,6 +32,14 @@ uv lock --check
uv sync --group dev
uv run python scripts/patch_lxst_pyogg_ogg_ctypes.py
+if [[ "$(uname -s)" == "Darwin" ]]; then
+ uv run python -c "
+import numpy
+from numpy._core._multiarray_umath import _add_newdoc_ufunc
+print('arm64 venv numpy', numpy.__version__, 'ok')
+"
+fi
+
if [[ "$(uname -s)" == "Darwin" ]]; then
if uv run python -c "import platform, sys; sys.exit(0 if platform.machine() == 'arm64' else 1)"; then
_miniaudio_state="$(uv run python -c "
diff --git a/scripts/ci/github-install-macos-x64-python-deps.sh b/scripts/ci/github-install-macos-x64-python-deps.sh
new file mode 100755
index 00000000..ffe0c977
--- /dev/null
+++ b/scripts/ci/github-install-macos-x64-python-deps.sh
@@ -0,0 +1,59 @@
+#!/usr/bin/env bash
+# Install locked Python deps for the darwin-x64 cx_Freeze slice on Apple Silicon CI.
+# The arm64 slice uses uv sync into .venv; this script mirrors that with .venv-x64 so
+# NumPy/LXST native wheels match the lockfile instead of unpinned pip -e . resolution.
+set -euo pipefail
+
+ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
+cd "$ROOT"
+
+PY_X64="${PY_X64:?PY_X64 must point at an x86_64 Python 3.14 interpreter}"
+
+if [[ "$(uname -s)" != "Darwin" ]]; then
+ echo "github-install-macos-x64-python-deps: skipping (not macOS)" >&2
+ exit 0
+fi
+
+export UV_PROJECT_ENVIRONMENT="${ROOT}/.venv-x64"
+export UV_PYTHON_INSTALL_DIR="${ROOT}/.cache/uv/python"
+
+uv lock --check
+
+if [[ -x /usr/local/bin/brew ]]; then
+ arch -x86_64 /usr/local/bin/brew install openssl@3
+fi
+
+_codec2="$(arch -x86_64 /usr/local/bin/brew --prefix codec2 2>/dev/null || true)"
+if [[ -n "$_codec2" && -d "${_codec2}/include" ]]; then
+ export LDFLAGS="${LDFLAGS:-} -L${_codec2}/lib -arch x86_64"
+ export CPPFLAGS="${CPPFLAGS:-} -I${_codec2}/include -arch x86_64"
+ export PKG_CONFIG_PATH="${_codec2}/lib/pkgconfig:${PKG_CONFIG_PATH:-}"
+fi
+
+if arch -x86_64 /usr/local/bin/brew --prefix openssl@3 >/dev/null 2>&1; then
+ _openssl="$(arch -x86_64 /usr/local/bin/brew --prefix openssl@3)"
+ export LDFLAGS="${LDFLAGS:-} -L${_openssl}/lib -arch x86_64"
+ export CPPFLAGS="${CPPFLAGS:-} -I${_openssl}/include -arch x86_64"
+ export PKG_CONFIG_PATH="${_openssl}/lib/pkgconfig:${PKG_CONFIG_PATH:-}"
+ export OPENSSL_DIR="${_openssl}"
+ export OPENSSL_LIB_DIR="${_openssl}/lib"
+ export OPENSSL_INCLUDE_DIR="${_openssl}/include"
+fi
+
+export ARCHFLAGS="${ARCHFLAGS:--arch x86_64}"
+export CC="${CC:-clang -arch x86_64}"
+export CXX="${CXX:-clang++ -arch x86_64}"
+export CFLAGS="${CFLAGS:--arch x86_64}"
+
+uv sync --frozen --group dev --python "$PY_X64"
+arch -x86_64 "${UV_PROJECT_ENVIRONMENT}/bin/python" scripts/patch_lxst_pyogg_ogg_ctypes.py
+
+arch -x86_64 "${UV_PROJECT_ENVIRONMENT}/bin/python" -c "
+import numpy
+from numpy._core._multiarray_umath import _add_newdoc_ufunc
+print('x64 venv numpy', numpy.__version__, 'ok')
+"
+
+if [[ -n "${GITHUB_ENV:-}" ]]; then
+ echo "PYTHON_CMD_X64=${UV_PROJECT_ENVIRONMENT}/bin/python" >>"$GITHUB_ENV"
+fi
diff --git a/scripts/unify-backend-plain-files.sh b/scripts/unify-backend-plain-files.sh
index e59170ba..56b9ae07 100755
--- a/scripts/unify-backend-plain-files.sh
+++ b/scripts/unify-backend-plain-files.sh
@@ -66,6 +66,16 @@ while IFS= read -r -d '' rel; do
filetype=$(file --brief --no-pad "$arm64_file" 2>/dev/null || true)
if [[ "$filetype" != Mach-O* ]]; then
+ pkg_dir="$(dirname "$rel")"
+ if find "$ARM64_DIR/$pkg_dir" "$X64_DIR/$pkg_dir" -maxdepth 1 \
+ \( -name '*.so' -o -name '*.dylib' -o -name '*.bundle' \) -print -quit 2>/dev/null | grep -q .; then
+ echo "unify-backend: ERROR: byte mismatch in a native Python package: $rel" >&2
+ echo " arm64 and x64 cx_Freeze trees differ under ${pkg_dir}/, which also" >&2
+ echo " contains native extensions. Copying one arch's .py over the other's" >&2
+ echo " .so breaks imports (e.g. NumPy _add_newdoc_ufunc). Rebuild the x64" >&2
+ echo " slice with scripts/ci/github-install-macos-x64-python-deps.sh." >&2
+ exit 1
+ fi
cp "$arm64_file" "$x64_file"
echo " unified: $rel"
unified=$((unified + 1))
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────